#include <stdio.h>
#include <e_file.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <grp.h>
#include <pwd.h>

#define  ARRAY_SIZE(x) ((sizeof(x)) / (sizeof(x[0]))) 

off_t file_size (struct stat s);
blkcnt_t file_blocks (struct stat s);
blksize_t file_ioblocks (struct stat s);
char file_type (struct stat s);
int file_mode (struct stat s, char **mode);
int get_file_uid_name (struct stat s, uid_t *uid, char **myuname);
int get_file_gid_name (struct stat s, gid_t *gid, char **mygname);

int main (int argc, char **argv)
{
	struct stat s;
	char *m = NULL;
	uid_t uid; 
	char *myuname = NULL;
	gid_t gid; 
	char *mygname = NULL;

	if (argc < 2) {
		return -1;
	}
	if (-1 == stat (argv[1], &s)){
		perror ("stat()");
		return -1;
	}
	printf ("文件：%s\n", argv[1]);
	printf ("大小：%ld\t\t 块：%ld\t\t  IO 块大小：%ld\t\t 类型：%c\n",\
			file_size(s), file_blocks(s), file_ioblocks(s), file_type(s));

	file_mode(s, &m);
	//获取uid和name 
	get_file_uid_name (s, &uid, &myuname);
	get_file_gid_name (s, &gid, &mygname);
	printf ("权限：%s\t\t Uid:(%d\t %s)  Gid:(%d\t %s)\n", m, uid, myuname, gid, mygname);
	return 0;
}

//文件的大小
off_t file_size (struct stat s)
{
	return s.st_size;
}
//块个数
blkcnt_t file_blocks (struct stat s)
{
	return s.st_blocks;
}
//IO块大小
blksize_t file_ioblocks (struct stat s)
{
	return s.st_blksize;
}
//类型
char file_type (struct stat s)
{
	char c = '\0';
	switch (s.st_mode & S_IFMT) {
		case S_IFSOCK:
			c = 's';
			break;
		case S_IFLNK:
			c = 'l';
			break;
		case S_IFREG:
			c = '-';
			break;
		case S_IFBLK:
			c = 'b';
			break;
		case S_IFDIR:
			c = 'd';
			break;
		case S_IFCHR:
			c = 'c';
			break;
		case S_IFIFO:
			c = 'p';
			break;
		default: 
			c = '?';
			break;
	}
	return c;
}

//将文件的权限信息回填到m中
int file_mode (struct stat s, char **mode)
{
	int all_mode[] = {S_IRUSR, S_IWUSR, S_IXUSR, \
		S_IRGRP, S_IWGRP, S_IXGRP,
		S_IROTH, S_IWOTH, S_IXOTH
	};
	//开辟存储空间
	*mode = calloc (10, sizeof(char));
	if (NULL == *mode) {
		perror ("calloc()");
		return -ENOMEM;
	}
	strncpy (*mode, "rwxrwxrwx", 10);
	for (int i = 0; i < ARRAY_SIZE(all_mode); i++) {
		if (!(s.st_mode & all_mode[i])) {
			//如果文件没有该权限写'-'
			(*mode)[i] = '-';
		}
	}
	return 0;
}

int get_file_uid_name (struct stat s, uid_t *uid, char **myuname)
{
	struct passwd *pswd = NULL;
	//先获取uid
	*uid = s.st_uid;
	pswd = getpwuid (*uid);
	if (NULL == pswd) {
		perror ("getpwuid()");
		return -1;
	}
	*myuname = malloc (strlen(pswd->pw_name)+1);
	memset (*myuname, '\0', (strlen(pswd->pw_name)+1));
	strncpy (*myuname, pswd->pw_name, strlen(pswd->pw_name));
	return 0;
}

//获取gid和group name
int get_file_gid_name (struct stat s, gid_t *gid, char **mygname)
{
	struct group *grp = NULL;
	*gid = s.st_gid;
	grp = getgrgid (*gid);
	if (NULL == grp) {
		perror ("getgrgid()");
		return -1;
	}
	*mygname = malloc (strlen(grp->gr_name));
	memset (*mygname, '\0', strlen(grp->gr_name));
	strcpy (*mygname, grp->gr_name);
	return 0;
}

